﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.VirtualEarth.MapControl;
using System.Windows.Media.Imaging;
using Microsoft.VirtualEarth.MapControl.Design;
using System.Text;
using System.Windows.Browser;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Windows.Resources;
using Vishcious.ArcGIS.SLContrib;
using Microsoft.VirtualEarth.MapControl.Core;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;


namespace VEExtended
{
    public partial class MainMap : UserControl
    {
        #region GLOBAL
        MapViewSpecificationConverter viewConverter = new MapViewSpecificationConverter();
        MapTileLayer customTileLayer = new MapTileLayer();

        MapLayer LayerShape = new MapLayer();
        Collection<ShapeFileXML> LayerData = new Collection<ShapeFileXML>();

        Border bLocationInfo = new Border();
        TextBlock tbLocationInfo = new TextBlock();
        MapLayer LocationInfo = new MapLayer();

        Border bMessageInfo = new Border();
        TextBlock tbMessageInfo = new TextBlock();
        MapLayer MessageInfo = new MapLayer();

        Border bNavigationInfoOver = new Border();
        Border bNavigationInfo = new Border();
        TextBlock tbNavigationInfo = new TextBlock();
        MapLayer NavigationInfo = new MapLayer();

        MiniMap miniMap = new MiniMap();
        MapLayer clickLayer = new MapLayer();

        //DOK
        MapLayer mlTerm = new MapLayer();
        MapLayer mlLine = new MapLayer();
        public Collection<Term> terms = new Collection<Term>();
        public Int32 activeTerm = 0;
        Border bback = new Border();
        bool ike = true;
        //DOK

        ProgressBar loadingBar = new ProgressBar();
        MapLayer LoadingLayer = new MapLayer();

        RecordInfo[] array = null;
        private string lastHeld;
        private int lastHeldCount;

        Double[] navigationLevels = new Double[25] {  0, 
            78271.52, 39135.76, 19567.88, 9783.94, 4891.97,
             2445.98,  1222.99,   611.5 ,  305.75,  152.87,
               76.44,    38.22,    19.11,    9.55,    4.78,
                2.39,     1.19,     0.6 ,    0.3 ,    0.15,
                0.07,     0.04,     0.02,    0.01};

        Int32[] navigationPx = new Int32[24]{  0, 
            195, 195, 195, 153, 152,
            152, 243, 243, 243, 243,
            195, 195, 156, 156, 156,
            156, 125, 125, 125, 156,
            125, 125, 125 };

        String[] navigationTxt = new String[24] {  "0", 
            "10.000km", "5.000km", "2.500km", "1.000km", "500km",
             "250km",  "200km",   "100km" ,  "50km",  "25km",
               "10km",    "5km",    "2km",   "1km",   "500m",
                "250m",     "100m",    "50m" ,    "25m",
                 "20m",     "10m",    "5m" ,    "2.5m"};
        #endregion GLOBAL
        /*##########################################################################################################################*/
        #region HIDDEN
        // Int32 totalRecords = 0;
        // Int32 totalPoints = 0;
        // Int32 visibleRecords = 0;
        // Int32 visiblePoints = 0;

        //1 - 78271 64px = 5000km-
        //2 - 39135 64px = 2500km-
        //3 - 19567 51px = 1000km-
        //4 - 9783 51px =  500km
        //5 - 4891 51px =  250km

        //6 - 2445 41px =  100km -
        //7 - 1222 41px =   50km -
        //8 - 611 66px =   40km -
        //9 - 305 66px =   20km -
        //10- 152 66px = 10km -

        //11- 76 66px = 5000m -
        //12- 38 52px = 2000m -
        //13- 19 52px = 1000m -
        //14- 9  52px = 500m -
        //15- 4  63px = 300m -

        //16- 2  63px = 150m -
        //17- 1  84px = 100m -
        //18- 0,6 83px = 50m -
        //19- 0,3 83px = 25m -
        //20- 0,15 67px = 10m -

        //21- 0,07 71px = 5m -
        //22- 0,04 75px = 3m -
        //23- 0,02 50px = 1m -
        //24- 0,01 100px = 1m -

        //1 - 195px = 10000km
        //2 - 195px = 5000km
        //3 - 195px = 2500km
        //4 - 153px = 1000km
        //5 - 152px = 500km

        //6 - 152px = 250km
        //7 - 243px = 200km
        //8 - 243px = 100km
        //9 - 243px = 50km
        //10- 243px = 25km

        //11- 195px = 10km
        //12- 195px = 5km
        //13- 156px = 2km
        //14- 156px = 1km
        //15- 156px = 500m

        //16- 156px = 250m
        //17- 125px = 100m
        //18- 125px = 50m
        //19- 125px = 25m
        //20
        #endregion HIDDEN
        /*##########################################################################################################################*/
        #region Initialize

        public bool MiniMapVisibility { get; set; }
        public bool ScaleVisibility { get; set; }
        public bool NavigationVisibility { get; set; }
        public bool LogoVisibility { get; set; }
        public bool CopyrightVisibility { get; set; }

        public bool OnlyCzechRepublic { get; set; }
        public bool LocationInfoVisibility { get; set; }
        public bool MessageVisibility { get; set; }

        public double Zoom { get; set; }
        public double Latitude { get; set; }
        public double Longitude { get; set; }

        public MainMap()
        {
            InitializeComponent();
            myMap.ViewChangeOnFrame += new EventHandler<MapEventArgs>(myMap_ViewChangeOnFrame); // Displays the current latitude and longitude as the map animates.
            myMap.KeyHeld += new EventHandler<MapKeyHeldEventArgs>(myMap_KeyHeld);
            myMap.MouseClick += new EventHandler<MapMouseEventArgs>(myMap_MouseClick);
            myMap.Children.Add(customTileLayer);
            myMap.Children.Add(bback);
            myMap.Children.Add(mlLine);
            myMap.Children.Add(mlTerm);
            myMap.Children.Add(LayerShape);
            myMap.Children.Add(clickLayer);

            myMap.AttachWheel(myMap_MouseWheel);

            createLocationInfo();
            createMessageInfo();
            createNavigationInfo();
            createMinimap();
            createLoadingBar();
        }


        private void myMap_Loaded(object sender, RoutedEventArgs e)
        {
            Update();
        }

        public void Update()
        {
            if (MiniMapVisibility) miniMap.Visibility = Visibility.Visible;
            else miniMap.Visibility = Visibility.Collapsed;

            if (ScaleVisibility) bNavigationInfoOver.Visibility = Visibility.Visible;
            else bNavigationInfoOver.Visibility = Visibility.Collapsed;

            if (NavigationVisibility) myMap.NavigationVisibility = Visibility.Visible;
            else myMap.NavigationVisibility = Visibility.Collapsed;

            if (LogoVisibility) myMap.LogoVisibility = Visibility.Visible;
            else myMap.LogoVisibility = Visibility.Collapsed;

            if (CopyrightVisibility) myMap.CopyrightVisibility = Visibility.Visible;
            else myMap.CopyrightVisibility = Visibility.Collapsed;

            if (LocationInfoVisibility) LocationInfo.Visibility = Visibility.Visible;
            else LocationInfo.Visibility = Visibility.Collapsed;

            if (MessageVisibility) MessageInfo.Visibility = Visibility.Visible;
            else MessageInfo.Visibility = Visibility.Collapsed;
        }


        private void createLocationInfo()
        {
            bLocationInfo.Background = new SolidColorBrush(Color.FromArgb(200, 0, 0, 0));
            bLocationInfo.VerticalAlignment = VerticalAlignment.Top;
            bLocationInfo.HorizontalAlignment = HorizontalAlignment.Right;
            bLocationInfo.BorderThickness = new Thickness(2);
            bLocationInfo.CornerRadius = new CornerRadius(5);
            bLocationInfo.Opacity = 0.6;
            bLocationInfo.Margin = new Thickness(10);
            bLocationInfo.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));

            tbLocationInfo.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
            tbLocationInfo.FontSize = 13;
            tbLocationInfo.Padding = new Thickness(5);
            tbLocationInfo.Opacity = 1;

            if (bLocationInfo.Child == null)
                bLocationInfo.Child = tbLocationInfo;
            if (!LocationInfo.Children.Contains(bLocationInfo))
                LocationInfo.AddChild(bLocationInfo);
            if (!myMap.Children.Contains(LocationInfo))
                myMap.Children.Add(LocationInfo);
        }


        private void createMessageInfo()
        {
            bMessageInfo.Background = new SolidColorBrush(Color.FromArgb(200, 0, 0, 0));
            bMessageInfo.VerticalAlignment = VerticalAlignment.Top;
            bMessageInfo.HorizontalAlignment = HorizontalAlignment.Center;
            bMessageInfo.BorderThickness = new Thickness(2);
            bMessageInfo.CornerRadius = new CornerRadius(5);
            bMessageInfo.Opacity = 0.6;
            bMessageInfo.Margin = new Thickness(10);
            bMessageInfo.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));

            tbMessageInfo.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
            tbMessageInfo.FontSize = 13;
            tbMessageInfo.Padding = new Thickness(5);
            tbMessageInfo.Opacity = 1;

            if (bMessageInfo.Child == null)
                bMessageInfo.Child = tbMessageInfo;
            if (!MessageInfo.Children.Contains(bMessageInfo))
                MessageInfo.AddChild(bMessageInfo);
            if (!myMap.Children.Contains(MessageInfo))
                myMap.Children.Add(MessageInfo);
        }

        private void createNavigationInfo()
        {
            bNavigationInfoOver.Background = new SolidColorBrush(Color.FromArgb(40, 0, 0, 0));
            bNavigationInfoOver.VerticalAlignment = VerticalAlignment.Bottom;
            bNavigationInfoOver.HorizontalAlignment = HorizontalAlignment.Left;
            bNavigationInfoOver.BorderThickness = new Thickness(2, 0, 2, 0);
            bNavigationInfoOver.CornerRadius = new CornerRadius(2);
            bNavigationInfoOver.Opacity = 0.6;
            bNavigationInfoOver.Margin = new Thickness(20);
            bNavigationInfoOver.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
            bNavigationInfoOver.Height = 30;

            bNavigationInfo.Background = new SolidColorBrush(Color.FromArgb(200, 0, 0, 0));
            bNavigationInfo.Opacity = 0.6;
            bNavigationInfo.Height = 18;

            tbNavigationInfo.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
            tbNavigationInfo.FontSize = 13;
            tbNavigationInfo.HorizontalAlignment = HorizontalAlignment.Center;
            tbNavigationInfo.VerticalAlignment = VerticalAlignment.Center;
            tbNavigationInfo.Opacity = 1;

            recalculateNavigation();

            if (bNavigationInfoOver.Child == null)
                bNavigationInfoOver.Child = bNavigationInfo;
            if (bNavigationInfo.Child == null)
                bNavigationInfo.Child = tbNavigationInfo;
            if (!NavigationInfo.Children.Contains(bNavigationInfoOver))
                NavigationInfo.AddChild(bNavigationInfoOver);
            if (!myMap.Children.Contains(NavigationInfo))
                myMap.Children.Add(NavigationInfo);
        }
        private void recalculateNavigation()
        {
            bNavigationInfoOver.Width = navigationPx[Convert.ToInt32(Math.Round(myMap.View.ZoomLevel))];
            tbNavigationInfo.Text = navigationTxt[Convert.ToInt32(Math.Round(myMap.View.ZoomLevel))];
        }

        private void createMinimap()
        {
            miniMap.HorizontalAlignment = HorizontalAlignment.Right;
            miniMap.VerticalAlignment = VerticalAlignment.Bottom;
            miniMap.Margin = new Thickness(20);
            if (!myMap.Children.Contains(miniMap))
                myMap.Children.Add(miniMap);
        }

        private void createLoadingBar()
        {
            loadingBar.Background = new SolidColorBrush(Color.FromArgb(200, 0, 0, 0));
            loadingBar.VerticalAlignment = VerticalAlignment.Bottom;
            loadingBar.HorizontalAlignment = HorizontalAlignment.Center;
            loadingBar.BorderThickness = new Thickness(2);
            loadingBar.Opacity = 0.7;
            loadingBar.Margin = new Thickness(10);
            loadingBar.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
            loadingBar.Width = 260;
            loadingBar.Height = 28;
            loadingBar.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));

            if (!myMap.Children.Contains(LoadingLayer))
                myMap.Children.Add(LoadingLayer);
            if (!LoadingLayer.Children.Contains(loadingBar))
                LoadingLayer.Children.Add(loadingBar);
        }

        #endregion Initialize
        /*##########################################################################################################################*/
        #region privateMethods

        private void myMap_MouseClick(object sender, MapMouseEventArgs e)
        {
            // Convert the X/Y Coordinate that was Clicked to a Lat/Long Location
            Map test = (Map)sender;
            var location = test.ViewportPointToLocation(e.ViewportPoint);

            //// Check if MapLayer has already been created
            ////AddLayer(clickLayer);
            //// Create Image 
            //MapLayer ml = AddImageToLayer(location);
            //Image image = (Image)ml.Children[0];

            //// Attach MouseEnter and MouseLeave Event Handler to the Rectangle
            //// This will be used to "Expand" the Rectangle when the user hovers the mouse over it
            //image.MouseEnter += new MouseEventHandler(image_MouseEnter);
            //image.MouseLeave += new MouseEventHandler(image_MouseLeave);
            //image.MouseLeftButtonDown += new MouseButtonEventHandler(image_MouseLeftButtonDown);
            //image.MouseLeftButtonUp += new MouseButtonEventHandler(image_MouseLeftButtonUp);
            //image.MouseMove += new MouseEventHandler(image_MouseMove);
            //// Center the Rectangle around the location
            ////PositionMethod position = PositionMethod.Center;
            //// Add Rectangle to MapLayer
            ////clickLayer.AddChild(ml, location, position);

            //TODO: uncoment for VEE

            if (!ike)
            {
                clickLayer.AddChild(AddEllipseToLayer(location, Colors.Orange, location.Latitude + "," + location.Longitude, 10, 111));
                Message(location.Latitude + "," + location.Longitude + ",0\n");
            }
        }


        private void myMap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (MiniMapVisibility)
                if (miniMap.Changed)
                {
                    myMap.Center = miniMap.Center;
                    miniMap.Changed = false;
                }
            RefreshLayerData();
        }


        private void myMap_MouseMove(object sender, MouseEventArgs e)
        {
            Double lat = myMap.View.Center.Latitude;
            Double lon = myMap.View.Center.Longitude;
            Double zoom = myMap.View.ZoomLevel;

            if (OnlyCzechRepublic)
            {
                Boolean changed = false;
                if (lat > 51.45783) { lat = 51; changed = true; }
                if (lat < 48.50052) { lat = 49; changed = true; }
                if (lon < 12.10873) { lon = 12; changed = true; }
                if (lon > 19.66683) { lon = 19; changed = true; }
                if (zoom < 8) { zoom = 8; changed = true; }
                if (zoom >= 8) { changed = true; }
                if (changed)
                    myMap.View = (MapViewSpecification)viewConverter.ConvertFrom(lat.ToString().Replace(",", ".") + "," + lon.ToString().Replace(",", ".") + ",0 " + zoom.ToString().Replace(",", ".") + " 0");
            }
        }


        private void myMap_TargetViewChanged(object sender, Microsoft.VirtualEarth.MapControl.MapEventArgs e)
        {
            miniMap.Center = myMap.Center;//change center of mini map
            miniMap.ZoomLevel = (myMap.ZoomLevel - 5) < 0 ? 1 : (myMap.ZoomLevel - 5);//make sure minimap is at least zoomlevel 1
        }


        /// <summary>
        /// event handler with map -> set latitute and longtitude
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param> 
        private void myMap_ViewChangeOnFrame(object sender, MapEventArgs e)
        {
            // Gets the current map view for this particular frame.
            MapViewSpecification mapViewSpec = myMap.View;
            Latitude = mapViewSpec.Center.Latitude;
            Latitude = mapViewSpec.Center.Longitude;
            Zoom = mapViewSpec.ZoomLevel;

            recalculateNavigation();

            if (LocationInfoVisibility)
            {
                LocationRect loc = myMap.GetBoundingRectangle();
                if (!ike)
                {
                    tbLocationInfo.Text = string.Format(CultureInfo.InvariantCulture, "Latitude: {0:F5} Longitude: {1:F5} ZoomLevel: {2} \r\n", myMap.View.Center.Latitude, myMap.View.Center.Longitude, myMap.View.ZoomLevel);
                    tbLocationInfo.Text += string.Format(CultureInfo.InvariantCulture, "Northwest(lat): {0:F5} Northwest(long): {1:F5} \r\n", loc.Northwest.Latitude, loc.Northwest.Longitude);
                    tbLocationInfo.Text += string.Format(CultureInfo.InvariantCulture, "Southeast(lat): {0:F5} Southeast(long: {1:F5}", loc.Southeast.Latitude, loc.Southeast.Longitude);
                }
                else
                {
                    tbLocationInfo.Text = string.Format(CultureInfo.InvariantCulture, "X: {1:F5} Y: {0:F5} Zoom: {2} ", myMap.View.Center.Latitude, myMap.View.Center.Longitude, myMap.View.ZoomLevel);
                }
            }
        }


        private void myMap_ViewChangeEnd(object sender, MapEventArgs e)
        {
            RefreshLayerData();
        }


        private void myMap_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            // MessageNew(string.Format("Delta: {0}. Location: {1},{2}", e.Delta, p.X, p.Y));
            Double lat = myMap.View.Center.Latitude;
            Double lon = myMap.View.Center.Longitude;
            Double zoom = Math.Round(myMap.View.ZoomLevel + e.Delta);

            SetMapView(lat, lon, zoom);
            e.Handled = true; //Prevents page from scrolling
        }


        private void myMap_KeyHeld(object sender, MapKeyHeldEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Key key in e.KeysHeld)
            {
                sb.Append('<');
                sb.Append(key.ToString());
                sb.Append('>');
            }
            string keysHeld = sb.ToString();
            if (0 == string.Compare(lastHeld, keysHeld))
                lastHeldCount++;
            else
            {
                lastHeld = keysHeld;
                lastHeldCount = 1;
            }

            sb.Append(": ");
            sb.Append(lastHeldCount);
        }


        private void XMLFileLoaded(object sender, OpenReadCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageNew(e.Error.Message);
                return;
            }
            try
            {
                using (Stream s = e.Result)
                {
                    XDocument xdoc = XDocument.Load(s);

                    List<ShapeFileXML> shapeList =
                        (from shape in xdoc.Descendants("ShapeFileXML")
                         select new ShapeFileXML()
                         {
                             ID = Convert.ToInt32(shape.Element("ID").Value),

                             Name = shape.Element("Name").Value,
                             ShapeType = (ShapeType)Convert.ToDouble(shape.Element("ShapeType").Value),
                             Visible = Convert.ToBoolean(shape.Element("Visible").Value),
                             XMin = Convert.ToInt32(shape.Element("XMin").Value),
                             XMax = Convert.ToInt32(shape.Element("XMax").Value),
                             YMin = Convert.ToInt32(shape.Element("YMin").Value),
                             YMax = Convert.ToInt32(shape.Element("YMax").Value),

                             Records = (from rec in xdoc.Descendants("ShapeRecord")
                                        select new ShapeRecord()
                                        {
                                            ID = Convert.ToInt32(rec.Element("ID").Value),
                                            NumberOfPoints = Convert.ToInt32(rec.Element("NumberOfPoints").Value),
                                            XMin = Convert.ToInt32(rec.Element("XMin").Value),
                                            XMax = Convert.ToInt32(rec.Element("XMax").Value),
                                            YMin = Convert.ToInt32(rec.Element("YMin").Value),
                                            YMax = Convert.ToInt32(rec.Element("YMax").Value),
                                            FillColor = new Converter().ColorFromString(rec.Element("FillColor").Value),
                                            StrokeColor = new Converter().ColorFromString(rec.Element("StrokeColor").Value),
                                            StrokeThickness = Convert.ToInt32(rec.Element("StrokeThickness").Value),
                                            Opacity = Convert.ToInt32(rec.Element("Opacity").Value),
                                            Locations = new Converter().LocationsFromString(rec.Element("Locations").Value)
                                        }).ToList<ShapeRecord>(),

                             Points = (from point in xdoc.Descendants("ShapePoint")
                                       select new ShapePoint()
                                           {
                                               ID = Convert.ToInt32(point.Element("ID").Value),
                                               Location = new Converter().LocationFromString(point.Element("Location").Value),
                                               URL = point.Element("URL").Value,
                                               Title = point.Element("Title").Value,
                                               Text = point.Element("Text").Value
                                           }).ToList<ShapePoint>()
                         }).ToList<ShapeFileXML>();

                    //Message(termList.Count.ToString());
                    AddShapeListToGraph(shapeList);   //A pak je šoupnu do grafu
                }
            }
            catch (Exception ex) { Message(ex.Message); }
        }


        private void SHPFileLoaded(object sender, OpenReadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                DateTime startTime = DateTime.Now;
                StreamResourceInfo photosDownloaded = new StreamResourceInfo(e.Result as Stream, null);
                ShapeFile shapeFileReader = new ShapeFile();
                shapeFileReader.ReadShapes(photosDownloaded.Stream);
                String shapeString = shapeFileReader.ToString();

                LocationRect loc = myMap.GetBoundingRectangle();

                ShapeFileXML sfXML = new ShapeFileXML();
                sfXML.NumberOfRecords = shapeFileReader.Records.Count;
                sfXML.NumberOfPoints = shapeFileReader.FileHeader.FileLength; //TODO: nevím, jestli zobrazuje správně délku (možná přepočítat body)
                sfXML.XMax = shapeFileReader.FileHeader.XMax;
                sfXML.XMin = shapeFileReader.FileHeader.XMin;
                sfXML.YMax = shapeFileReader.FileHeader.YMax;
                sfXML.YMin = shapeFileReader.FileHeader.YMin;
                sfXML.ShapeType = (ShapeType)shapeFileReader.FileHeader.ShapeType;
                sfXML.Visible = true;
                sfXML.ID = LayerData.Count;

                int recordCounter = 0;
                foreach (ShapeFileRecord record in shapeFileReader.Records)
                {
                    ShapeRecord sr = new ShapeRecord();
                    sr.ID = recordCounter;
                    sr.NumberOfPoints = record.NumberOfPoints;
                    sr.XMax = record.XMax;
                    sr.XMin = record.XMin;
                    sr.YMax = record.YMax;
                    sr.YMin = record.YMin;

                    LocationCollection locColection = new LocationCollection();
                    foreach (Point p in record.Points)
                    {
                        locColection.Add(new Location() { Latitude = p.Y, Longitude = p.X });
                    }
                    sr.Locations = locColection;
                    sfXML.Records.Add(sr);
                    recordCounter++;
                }


                // Message("FileLength: " + shapeFileReader.FileHeader.FileLength + "\n" +
                //    "TotalRecords: " + totalRecords + "\n" +
                //    "TotalPoints: " + totalPoints + "\n" +
                //    "RecordsInArea: " + recordsInArea + "\n" +
                //    "PointsInArea: " + pointsInArea + "\n" +
                //    "VisibleRecords: " + visibleRecords + "\n" +
                //    "VisiblePoints: " + visiblePoints + "\n" +
                //  "TotalSeconds: " + totalTime.TotalSeconds);
                //IsoWriteSHP(sfXML);
                LayerData.Add(sfXML);
                RefreshLayerData();
                DateTime endTime = DateTime.Now;
                TimeSpan totalTime = endTime - startTime;

                Message("TotalSeconds: " + totalTime.TotalSeconds);
            }
            else { Message(e.Error.Message); }
        }

        /// <summary>
        /// MAJOR CLASS TO DRAW LAYER DATA
        /// </summary>
        public void RefreshLayerData()
        {
            LoadingLayer.Visibility = Visibility.Visible;
            loadingBar.Value = 0;
            int visiblePoints = 0;
            int totalPoints = 0;
            int totalRecords = 0;
            LocationRect loc = myMap.GetBoundingRectangle();
            Location A = loc.Northwest; Location B = loc.Northeast; Location C = loc.Southeast; Location D = loc.Southwest;
            if (!ike)
                Message();
            LayerShape.Children.Clear();
            foreach (ShapeFileXML shape in LayerData)
            {
                Int16 startRegionOut = 0; Int16 lastRegionIn = 0; Int16 lastRegionOut = 0; Int16 lastRegionOver = 0;
                Int32 region1 = 0; Int32 region2 = 0; Int32 region3 = 0; Int32 region4 = 0; Int32 region5 = 0;
                Int32 region6 = 0; Int32 region7 = 0; Int32 region8 = 0; Int32 region9 = 0; Int32 region0 = 0;
                loadingBar.Value = 5;
                if (shape.Visible == true)
                {
                    #region RECORDS
                    if ((shape.ShapeType != ShapeType.Point) && (shape.ShapeType != ShapeType.NullShape))
                        foreach (ShapeRecord record in shape.Records)
                        {
                            #region CALCULATE
                            loadingBar.Value = 10;
                            totalPoints += record.Locations.Count;
                            totalRecords++;

                            foreach (Location X in record.Locations)
                                if ((X.Latitude > A.Latitude) && (X.Longitude < A.Longitude)) //region 1
                                { region1++; }
                                else if ((X.Latitude > A.Latitude) && (A.Longitude < X.Longitude) && (X.Longitude < B.Longitude)) //region 2
                                { region2++; }
                                else if ((B.Latitude < X.Latitude) && (B.Longitude < X.Longitude)) //region 3
                                { region3++; }
                                else if ((X.Longitude < A.Longitude) && (A.Latitude > X.Latitude) && (X.Latitude > D.Latitude)) //region 4
                                { region4++; }
                                else if ((A.Latitude > X.Latitude) && (A.Longitude < X.Longitude) && (X.Latitude > C.Latitude) && (X.Longitude < C.Longitude)) //region 5
                                { region5++; }
                                else if ((B.Longitude < X.Longitude) && (B.Latitude > X.Latitude) && (X.Latitude > C.Latitude)) //region 6
                                { region6++; }
                                else if ((D.Latitude > X.Latitude) && (X.Longitude < D.Longitude)) //region 7
                                { region7++; }
                                else if ((D.Latitude > X.Latitude) && (D.Longitude < X.Longitude) && (X.Longitude < C.Longitude)) //region 8
                                { region8++; }
                                else if ((C.Latitude > X.Latitude) && (C.Longitude < X.Longitude)) //region 9
                                { region9++; }
                                else //something wrong
                                { region0++; }

                            if (region5 == 0) continue;
                            double mod = region5 / 500;
                            //if (mod < 1) mod = 1;

                            #endregion CALCULATE
                            loadingBar.Value = 15;
                            #region FILLING
                            int pointsInArea = 0;
                            LocationCollection locColection = new LocationCollection();

                            foreach (Location X in record.Locations)//while (ai * 5000 < record.Locations.Count)
                            {
                                if ((X.Latitude > A.Latitude) && (X.Longitude < A.Longitude)) //region 1
                                { lastRegionOver = 1; }
                                else if ((X.Latitude > A.Latitude) && (A.Longitude < X.Longitude) && (X.Longitude < B.Longitude)) //region 2
                                {
                                    if (lastRegionIn == 5) lastRegionOut = 2;
                                    if (lastRegionIn == 0) startRegionOut = 2;
                                    lastRegionIn = 2;
                                }
                                else if ((B.Latitude < X.Latitude) && (B.Longitude < X.Longitude)) //region 3
                                { lastRegionOver = 3; }
                                else if ((X.Longitude < A.Longitude) && (A.Latitude > X.Latitude) && (X.Latitude > D.Latitude)) //region 4
                                {
                                    if (lastRegionIn == 5) lastRegionOut = 4;
                                    if (lastRegionIn == 0) startRegionOut = 4;
                                    lastRegionIn = 4;
                                }
                                else if ((A.Latitude > X.Latitude) && (A.Longitude < X.Longitude) && (X.Latitude > C.Latitude) && (X.Longitude < C.Longitude)) //region 5
                                {
                                    pointsInArea++;
                                    //    if ((pointsInArea % mod == 0) || (pointsInArea < 500))
                                    {
                                        if (lastRegionIn == 2)
                                        {
                                            if (lastRegionOut == 4)
                                                locColection.Add(A);
                                            if (lastRegionOut == 6)
                                                locColection.Add(B);
                                            if (lastRegionOut == 8)
                                            {
                                                if (lastRegionOver == 1)
                                                { locColection.Add(D); locColection.Add(A); }
                                                else if (lastRegionOver == 3)
                                                { locColection.Add(C); locColection.Add(B); }
                                            }
                                        }
                                        else if (lastRegionIn == 4)
                                        {
                                            if (lastRegionOut == 2)
                                                locColection.Add(A);
                                            if (lastRegionOut == 8)
                                                locColection.Add(D);
                                            if (lastRegionOut == 6)
                                            {
                                                if (lastRegionOver == 1)
                                                { locColection.Add(B); locColection.Add(A); }
                                                else if (lastRegionOver == 7)
                                                { locColection.Add(C); locColection.Add(D); }
                                            }
                                        }
                                        else if (lastRegionIn == 6)
                                        {
                                            if (lastRegionOut == 2)
                                                locColection.Add(B);
                                            if (lastRegionOut == 8)
                                                locColection.Add(D);
                                            if (lastRegionOut == 4)
                                            {
                                                if (lastRegionOver == 9)
                                                { locColection.Add(A); locColection.Add(B); }
                                                else if (lastRegionOver == 3)
                                                { locColection.Add(D); locColection.Add(C); }
                                            }
                                        }
                                        if (lastRegionIn == 8)
                                        {
                                            if (lastRegionOut == 4)
                                                locColection.Add(D);
                                            if (lastRegionOut == 6)
                                                locColection.Add(C);
                                            if (lastRegionOut == 2)
                                            {
                                                if (lastRegionOver == 7)
                                                { locColection.Add(A); locColection.Add(D); }
                                                else if (lastRegionOver == 9)
                                                { locColection.Add(B); locColection.Add(C); }
                                            }
                                        }

                                        lastRegionIn = 5;
                                        locColection.Add(X);
                                        visiblePoints++;
                                    }
                                }
                                else if ((B.Longitude < X.Longitude) && (B.Latitude > X.Latitude) && (X.Latitude > C.Latitude)) //region 6
                                {
                                    if (lastRegionIn == 5) lastRegionOut = 6;
                                    if (lastRegionIn == 0) startRegionOut = 6;
                                    lastRegionIn = 6;
                                }
                                else if ((D.Latitude > X.Latitude) && (X.Longitude < D.Longitude)) //region 7
                                { lastRegionOver = 7; }
                                else if ((D.Latitude > X.Latitude) && (D.Longitude < X.Longitude) && (X.Longitude < C.Longitude)) //region 8
                                {
                                    if (lastRegionIn == 5) lastRegionOut = 8;
                                    if (lastRegionIn == 0) startRegionOut = 8;
                                    lastRegionIn = 8;
                                }
                                else if ((C.Latitude > X.Latitude) && (C.Longitude < X.Longitude)) //region 9
                                { lastRegionOver = 9; }
                                else //something wrong
                                { }

                            }
                            loadingBar.Value = 50;

                            //if zero start out


                            if (startRegionOut == 2)
                            {
                                if (lastRegionOut == 4)
                                    locColection.Add(A);
                                if (lastRegionOut == 6)
                                    locColection.Add(B);
                                if (lastRegionOut == 8)
                                {
                                    if (lastRegionOver == 1)
                                    { locColection.Add(D); locColection.Add(A); }
                                    else if (lastRegionOver == 3)
                                    { locColection.Add(C); locColection.Add(B); }
                                }
                            }
                            else if (startRegionOut == 4)
                            {
                                if (lastRegionOut == 2)
                                    locColection.Add(A);
                                if (lastRegionOut == 8)
                                    locColection.Add(D);
                                if (lastRegionOut == 6)
                                {
                                    if (lastRegionOver == 1)
                                    { locColection.Add(B); locColection.Add(A); }
                                    else if (lastRegionOver == 7)
                                    { locColection.Add(C); locColection.Add(D); }
                                }
                            }
                            else if (startRegionOut == 6)
                            {
                                if (lastRegionOut == 2)
                                    locColection.Add(B);
                                if (lastRegionOut == 8)
                                    locColection.Add(D);
                                if (lastRegionOut == 4)
                                {
                                    if (lastRegionOver == 9)
                                    { locColection.Add(A); locColection.Add(B); }
                                    else if (lastRegionOver == 3)
                                    { locColection.Add(D); locColection.Add(C); }
                                }
                            }
                            else if (startRegionOut == 8)
                            {
                                if (lastRegionOut == 4)
                                    locColection.Add(D);
                                if (lastRegionOut == 6)
                                    locColection.Add(C);
                                if (lastRegionOut == 2)
                                {
                                    if (lastRegionOver == 7)
                                    { locColection.Add(A); locColection.Add(D); }
                                    else if (lastRegionOver == 9)
                                    { locColection.Add(B); locColection.Add(C); }
                                }
                            }
                            loadingBar.Value = 60;
                            #endregion FILLING

                            #region DRAWING
                            if (shape.ShapeType == ShapeType.Polygon)
                            {
                                MapPolygon polygon = new MapPolygon();
                                polygon.Fill = new SolidColorBrush(Colors.Blue);
                                polygon.Stroke = new SolidColorBrush(Colors.Yellow);
                                polygon.StrokeThickness = 2;
                                polygon.Opacity = 0.5;
                                polygon.Locations = record.Locations;
                                polygon.Locations = locColection;
                                LayerShape.AddChild(polygon);
                            }
                            else if (shape.ShapeType == ShapeType.PolyLine)
                            {
                                MapPolyline polyline = new MapPolyline();
                                polyline.Stroke = new SolidColorBrush(Colors.Brown);
                                polyline.StrokeThickness = 2;
                                polyline.Opacity = 0.8;
                                polyline.Locations = record.Locations;
                                polyline.Locations = locColection;
                                LayerShape.AddChild(polyline);
                            }

                            #endregion DRAWING
                        }
                    #endregion RECORDS
                    loadingBar.Value = 70;
                    #region POINTS
                    if (shape.ShapeType == ShapeType.Point)
                        foreach (ShapePoint point in shape.Points)
                        {
                            totalPoints++;
                            if ((A.Latitude > point.Location.Latitude) && (A.Longitude < point.Location.Longitude) && (point.Location.Latitude > C.Latitude) && (point.Location.Longitude < C.Longitude))
                            {
                                if (point.URL != "")
                                    LayerShape.AddChild(AddImageToLayer(point.Location, point.URL, point.Title, point.Text));
                                else
                                    LayerShape.AddChild(AddEllipseToLayer(point.Location, Colors.Orange, point.Title, 5));
                                visiblePoints++;
                            }
                            loadingBar.Value = 80;
                        }
                    #endregion POINTS
                }
                if (!ike)
                {
                    Message("R0: " + region0 + " R1: " + region1 + " R2: " + region2 + " R3: " + region3 + " R4: " + region4);
                    Message("R5: " + region5 + " R6: " + region6 + " R7: " + region7 + " R8: " + region8 + " R9: " + region9);
                }
            }
            if (!ike)
            {
                Message("Visible records: " + totalRecords);
                Message("Total    points: " + totalPoints);
                Message("Visible  points: " + visiblePoints);
            }
            loadingBar.Value = 100;
            LoadingLayer.Visibility = Visibility.Collapsed;
        }

        private void IsoWriteSHP(ShapeFileXML sfXML)
        {
            try
            {
                using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    // Create new file
                    using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream("shapeSource.xml", FileMode.Create, isoStore))
                    {
                        // Write to the Isolated Storage for the user.
                        XmlWriterSettings settings = new XmlWriterSettings();
                        settings.Indent = true;
                        // Create an XmlWriter.
                        using (XmlWriter writer = XmlWriter.Create(isoStream, settings))
                        {
                            XElement records = new XElement("Shapes");
                            foreach (ShapeRecord sr in sfXML.Records)
                            {
                                String loc = "";
                                foreach (Location l in sr.Locations)
                                {
                                    loc += l.Latitude + "." + l.Longitude + "\n";
                                }
                                XElement record =
                                    new XElement("Record", new XAttribute("ID", sr.ID),
                                        new XElement("xMin", sr.XMin),
                                        new XElement("xMax", sr.XMax),
                                        new XElement("yMin", sr.YMin),
                                        new XElement("yMax", sr.YMax),
                                        new XElement("numberOfPoints", sr.NumberOfPoints),
                                        new XElement("location", loc));
                                records.Add(record);
                            }

                            XElement shapeFile =
                                new XElement("ShapeFile",
                                new XElement("name", sfXML.Name),
                                new XElement("shapeType", (int)sfXML.ShapeType),
                                new XElement("xMin", sfXML.XMin),
                                new XElement("xMax", sfXML.XMax),
                                new XElement("yMin", sfXML.YMin),
                                new XElement("yMax", sfXML.YMax),
                                new XElement("numberOfPoints", sfXML.NumberOfPoints),
                                new XElement("numberOfRecords", sfXML.NumberOfRecords),
                                new XElement(records));


                            XDocument myXml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
                                  new XComment("A Comment in the XML"), shapeFile);
                            myXml.Save(writer);
                            writer.Flush();
                        }
                    }
                }
            }
            catch (Exception ex) { Message(ex.Message); }
        }
        #endregion privateMethods
        /*##########################################################################################################################*/
        #region publicMethods


        public void SetMapView(double latitude, double longitude, double zoom)
        {
            myMap.View = (MapViewSpecification)viewConverter.ConvertFrom(latitude.ToString().Replace(",", ".") + "," + longitude.ToString().Replace(",", ".") + ",0 " + zoom.ToString().Replace(",", ".") + " 0");
        }


        public void SetTileLayer(TileMap.Mode mode)
        {
            myMap.Mode = new Microsoft.VirtualEarth.MapControl.Core.MercatorMode();
            customTileLayer.TileSources.Clear();
            switch (mode)
            {
                case TileMap.Mode.OpenAerial: { customTileLayer.TileSources.Add(new TileMap.OpenAerialMapTileSource()); } break;
                case TileMap.Mode.OpenStreet: { customTileLayer.TileSources.Add(new TileMap.OpenStreetMapTileSource()); } break;
                case TileMap.Mode.YahooAerial: { customTileLayer.TileSources.Add(new TileMap.YahooAerialTileSource()); } break;
                case TileMap.Mode.YahooHybrid: { customTileLayer.TileSources.Add(new TileMap.YahooAerialTileSource()); customTileLayer.TileSources.Add(new TileMap.YahooHybridTileSource()); } break;
                case TileMap.Mode.YahooStreet: { customTileLayer.TileSources.Add(new TileMap.YahooStreetTileSource()); } break;
                case TileMap.Mode.BingStreet: { myMap.Mode = new RoadMode(); } break;
                case TileMap.Mode.BingAerial: { myMap.Mode = new AerialMode(); } break;
                case TileMap.Mode.Null: { customTileLayer.TileSources.Add(new TileMap.NullTileSource()); } break;
            }
        }


        public void LoadXMLFile(String url)
        {
            WebClient wc = new WebClient();
            wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
            wc.OpenReadCompleted += XMLFileLoaded;
            wc.OpenReadAsync(new Uri(url, UriKind.RelativeOrAbsolute)); //"sampleXML.xml"
        }

        public void LoadSHPFile(String url)
        {
            WebClient wc = new WebClient();
            wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
            wc.OpenReadCompleted += new OpenReadCompletedEventHandler(SHPFileLoaded);
            wc.OpenReadAsync(new Uri(url, UriKind.RelativeOrAbsolute)); //STATES "states.shp"
        }

        void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            // Progress Updates
            //  Message(e.ProgressPercentage.ToString());
            if (loadingBar.Value == 100) LoadingLayer.Visibility = Visibility.Collapsed;
            else LoadingLayer.Visibility = Visibility.Visible;
            loadingBar.Value = e.ProgressPercentage;
        }

        //not used
        public void AddShpToMap(FileInfo shapeFile, FileInfo dbfFile)
        {
            //Read the SHP and DBF files into the ShapeFileReader
            ShapeFile shapeFileReader = new ShapeFile();
            if (shapeFile != null && dbfFile != null)
            {
                shapeFileReader.Read(shapeFile, dbfFile);
            }
            else
            {
                HtmlPage.Window.Alert("Please select a SP and a DBF file to proceed.");
                return;
            }

            foreach (ShapeFileRecord record in shapeFileReader.Records)
            {
                MapPolygon polygon = new MapPolygon();
                polygon.Fill = new SolidColorBrush(Colors.Blue);
                polygon.Stroke = new SolidColorBrush(Colors.Yellow);
                polygon.StrokeThickness = 2;
                polygon.Opacity = 0.5;

                LocationCollection locColection = new LocationCollection();
                for (int i = 0; i < record.Points.Count; i++)
                {
                    locColection.Add(new Location() { Latitude = record.Points[i].Y, Longitude = record.Points[i].X });
                }
                polygon.Locations = locColection;
                myMap.AddChild(polygon);

                Message(record.ToString(), true);
            }
        }


        public MapLayer AddEllipseToLayer(Location location, Color color, String text, Int32 size)
        {
            return AddEllipseToLayer(location, color, text, size, 0);
        }


        public MapLayer AddEllipseToLayer(Location location, Color color, String text, Int32 size, Int32 ID)
        {
            MapLayer myLayer = new MapLayer();
            Canvas canvas = new Canvas();
            Double topProperty = 4 * size - ((text.Length / 10) * 0.5 * size);

            canvas.Width = size * 10;
            canvas.Height = size * 10;
            canvas.MouseEnter += new MouseEventHandler(canvas_MouseEnter);
            canvas.MouseLeave += new MouseEventHandler(canvas_MouseLeave);
            canvas.MouseLeftButtonDown += new MouseButtonEventHandler(canvas_MouseLeftButtonDown);
            canvas.Tag = ID;

            // Set ellipse
            Ellipse ellipse = new Ellipse();
            ellipse.Stroke = new SolidColorBrush(Colors.Black);
            ellipse.Stroke.Opacity = 0.6;
            ellipse.StrokeThickness = 2;
            ellipse.Fill = new SolidColorBrush(color);
            ellipse.Width = canvas.Width;
            ellipse.Height = canvas.Height;
            ellipse.Opacity = size / 10.0;
            ellipse.Stretch = Stretch.Fill;
            //ellipse.SetValue(Canvas.TopProperty, 20.0);
            //ellipse.SetValue(Canvas.LeftProperty, 40.0);

            // Set text
            TextBlock title = new TextBlock();
            title.FontWeight = FontWeights.Bold;
            title.FontSize = size + 2;
            title.Text = text;
            title.VerticalAlignment = VerticalAlignment.Center;
            title.TextAlignment = TextAlignment.Center;
            title.SetValue(Canvas.TopProperty, topProperty);
            title.SetValue(Canvas.LeftProperty, 4.0);
            title.Width = canvas.Width - 4;
            title.TextWrapping = TextWrapping.Wrap;

            // Add Things to the Layer 
            canvas.Children.Add(ellipse);
            canvas.Children.Add(title);

            PositionMethod position = PositionMethod.Center;
            myLayer.AddChild(canvas, location, position);

            return myLayer;
        }


        public MapLayer AddLineToLayer(Location locationStart, Location locationEnd, Color color, Double size)
        {
            MapLayer myLayer = new MapLayer();
            MapPolyline polyline = new MapPolyline();

            polyline.Stroke = new SolidColorBrush(color);
            polyline.StrokeThickness = size;
            polyline.Opacity = 0.2;

            LocationCollection locColection = new LocationCollection();
            locColection.Add(locationStart);
            locColection.Add(locationEnd);
            polyline.Locations = locColection;

            myLayer.AddChild(polyline);
            return myLayer;
        }


        public MapLayer AddImageToLayer(Location location)
        {
            return AddImageToLayer(location, @"/Images/Icons/223.png", "", "");
        }


        public MapLayer AddImageToLayer(Location Location, String Url, String title, String text)
        {
            MapLayer myLayer = new MapLayer();

            // Create Image 
            Image image = new Image();
            // Set the Image Source 
            image.Source = new BitmapImage(new Uri(Url, UriKind.RelativeOrAbsolute));

            //Scale Image
            ScaleTransform scaleTransform = new ScaleTransform();
            scaleTransform.ScaleX = 0.125;
            scaleTransform.ScaleY = 0.125;
            scaleTransform.CenterX = 128;
            scaleTransform.CenterY = 128;
            image.RenderTransform = scaleTransform;

            // Set Image Display Properties 
            image.Opacity = 0.8;
            image.Stretch = Stretch.None;
            PositionMethod position = PositionMethod.Center;

            // Add Tooltip 
            StackPanel tooltipObject = new StackPanel();
            TextBlock tbTitle = new TextBlock();
            tbTitle.FontWeight = FontWeights.Bold;
            tbTitle.Text = title;//"The Point"
            tooltipObject.Children.Add(tbTitle);
            TextBlock description = new TextBlock();
            description.Text = text;//"This is a point located at [" + Location.Latitude + "," + Location.Longitude + "].";
            tooltipObject.Children.Add(description);
            ToolTipService.SetToolTip(image, tooltipObject);

            // Add Image to the Layer 
            myLayer.AddChild(image, Location, position);

            return myLayer;
        }


        // sets message on top center place in map(PointsInfoVisiblity must be set to TRUE)
        public void Message(String messageText)
        {
            if (tbMessageInfo.Text == "")
                tbMessageInfo.Text += messageText;
            else
                tbMessageInfo.Text += messageText + "\n"; ;
        }

        // <param name="newLine">if true, then next message starts new line</param>
        public void Message(String messageText, Boolean newLine)
        {
            if (newLine) { tbMessageInfo.Text += "\n"; }
            tbMessageInfo.Text += messageText;
        }

        // Clear all messages
        public void Message()
        {
            tbMessageInfo.Text = "";
        }

        // sets New message on top center place in map(PointsInfoVisiblity must be set to TRUE)
        public void MessageNew(String messageText)
        {
            tbMessageInfo.Text = messageText;
        }


        #endregion publicMethods
        /*##########################################################################################################################*/
        #region LayerThings

        public void AddShapeListToGraph(List<ShapeFileXML> shapeList)
        {
            foreach (ShapeFileXML shape in shapeList)
            {
                AddShapeToGraph(shape);
            }
        }

        public void AddShapeToGraph(ShapeFileXML shape)
        {
            bool exist = false;
            foreach (ShapeFileXML sf in LayerData)
                if (shape.ID == sf.ID)
                    exist = true;
            if (!exist)
            {
                LayerData.Add(shape);
            }
        }

        public void ShowLayer(Int32 ID)
        {
            for (int i = 0; i < LayerData.Count; i++)
                if (LayerData[i].ID == ID) LayerData[i].Visible = true;
            RefreshLayerData();
        }


        public void HideLayer(Int32 ID)
        {
            for (int i = 0; i < LayerData.Count; i++)
                if (LayerData[i].ID == ID) LayerData[i].Visible = false;
            RefreshLayerData();
        }


        public void RemoveLayer(Int32 ID)
        {
            for (int i = 0; i < LayerData.Count; i++)
                if (LayerData[i].ID == ID) LayerData[i] = null;
            RefreshLayerData();
        }


        public Int32 CountShapeFiles()
        {
            return LayerData.Count;
        }


        public void setUrlWithParams(Int32 ID)
        {
            try
            {
                string patha = "?ID=" + ID;
                Uri LocationUri2 = new Uri(GetUrl(patha), UriKind.Absolute);
                HtmlPage.Window.Navigate(LocationUri2);
            }
            catch (Exception ex) { HtmlPage.Window.Alert(ex.Message); }
        }


        private string GetUrl(string finalUrl)
        {
            string path = HtmlPage.Document.DocumentUri.AbsolutePath;
            int lastSlash = path.LastIndexOf("/");
            string port = ":" + HtmlPage.Document.DocumentUri.Port;
            return "http://" + HtmlPage.Document.DocumentUri.Host + port + path + finalUrl;
        }

        #endregion LayerThings
        /*##########################################################################################################################*/
        #region otherMethods


        private void image_MouseEnter(object sender, MouseEventArgs e)
        {
            // Get the Rectangle
            var image = (Image)sender;

            // Create new ScaleTransform
            var scaleTransform = new ScaleTransform();

            // Set the Transform to "Expand" the Rectangle
            // equally horizontally and vertically
            scaleTransform.ScaleX = 0.25;
            scaleTransform.ScaleY = 0.25;

            // Set the Scale Center to the Center of the Rectangle
            // This is so it doesn't move when "Expanded"
            scaleTransform.CenterX = 128;//image.Width / 5;
            scaleTransform.CenterY = 128;//image.Height / 5;

            // Apply the ScaleTransform to the Rectangle
            image.RenderTransform = scaleTransform;
        }

        private void image_MouseLeave(object sender, MouseEventArgs e)
        {
            // Get the Rectangle
            var image = (Image)sender;
            var scaleTransform = new ScaleTransform();
            // Set the Transform to "Expand" the Rectangle
            // equally horizontally and vertically
            scaleTransform.ScaleX = 0.125;
            scaleTransform.ScaleY = 0.125;

            // Set the Scale Center to the Center of the Rectangle
            // This is so it doesn't move when "Expanded"
            scaleTransform.CenterX = 128;//image.Width / 20;
            scaleTransform.CenterY = 128;//image.Height / 20;

            // Remove the ScaleTransform
            image.RenderTransform = scaleTransform;
        }

        Boolean mouseDown = false;

        private void image_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            mouseDown = true;
        }

        private void image_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            mouseDown = false;
        }

        private void image_MouseMove(object sender, MouseEventArgs e)
        {
            if (mouseDown)
            {
                // Get the Rectangle
                var image = (Image)sender;
                var location = new Location(myMap.Center.Latitude, myMap.Center.Longitude); //myMap.ViewportPointToLocation(e.GetPosition(myMap.Center.));


                Image img = new Image();
                // Set the Image Source 
                img.Source = new BitmapImage(new Uri(@"/Images/Icons/223.png", UriKind.Relative));

                // Add Tooltip 
                var tooltipObject = new StackPanel();
                var title = new TextBlock();
                title.FontWeight = FontWeights.Bold;
                title.Text = "The Point";
                tooltipObject.Children.Add(title);
                var description = new TextBlock();
                description.Text = "This is a point located at [" + location.Latitude + "," + location.Longitude + "].";
                tooltipObject.Children.Add(description);
                ToolTipService.SetToolTip(img, tooltipObject);

                //Scale Image
                var scaleTransform = new ScaleTransform();
                scaleTransform.ScaleX = 0.125;
                scaleTransform.ScaleY = 0.125;
                scaleTransform.CenterX = 128;
                scaleTransform.CenterY = 128;
                img.RenderTransform = scaleTransform;

                img.Opacity = 0.8;
                img.Stretch = Stretch.None;

                // Attach MouseEnter and MouseLeave Event Handler to the Rectangle
                // This will be used to "Expand" the Rectangle when the user hovers the mouse over it
                img.MouseEnter += new MouseEventHandler(image_MouseEnter);
                img.MouseLeave += new MouseEventHandler(image_MouseLeave);
                img.MouseLeftButtonDown += new MouseButtonEventHandler(image_MouseLeftButtonDown);
                img.MouseLeftButtonUp += new MouseButtonEventHandler(image_MouseLeftButtonUp);
                img.MouseMove += new MouseEventHandler(image_MouseMove);


                PositionMethod position = PositionMethod.Center;
                // Add Rectangle to MapLayer
                clickLayer.RemoveChild(image);
                clickLayer.AddChild(img, location, position);
            }
        }


        private void btnTest1_Click(object sender, RoutedEventArgs e)
        {

        }


        private void QuickSort(int top, int bottom)
        {
            // top = subscript of beginning of array
            // bottom = subscript of end of array

            int middle = 0;
            if (top < bottom)
            {
                middle = partition(top, bottom);
                QuickSort(top, middle);   // sort first section
                QuickSort(middle + 1, bottom);    // sort second section
            }
        }

        private int partition(int top, int bottom)
        {
            int x = array[top].Points;
            int i = top - 1;
            int j = bottom + 1;
            RecordInfo temp;
            do
            {
                do
                {
                    j--;
                } while (x > array[j].Points);

                do
                {
                    i++;
                } while (x < array[i].Points);

                if (i < j)
                {
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            } while (i < j);
            return j;           // returns middle subscript  
        }


        private void canvas_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            Int32 clickedTerm = Convert.ToInt32(((Canvas)sender).Tag);
            if ((activeTerm != clickedTerm) && (clickedTerm != getRootTerm().TermID))
            {
                activeTerm = clickedTerm;
                Term tt = getTerm(activeTerm);
                PaintTermChild(tt);

                SetMapView(tt.Bubble.Location.Latitude, tt.Bubble.Location.Longitude, Zoom);
            }
        }

        private void canvas_MouseEnter(object sender, MouseEventArgs e)
        {
            Canvas canvas = (Canvas)sender;
            ScaleTransform scaleTransform = new ScaleTransform();
            if (canvas.Width < 32)
            {
                scaleTransform.ScaleX = 2.3;
                scaleTransform.ScaleY = 2.3;
            }
            else if (canvas.Width < 48)
            {
                scaleTransform.ScaleX = 1.7;
                scaleTransform.ScaleY = 1.7;
            }
            else if (canvas.Width > 48)
            {
                scaleTransform.ScaleX = 1.3;
                scaleTransform.ScaleY = 1.3;
            }
            else
            {
                scaleTransform.ScaleX = 1.1;
                scaleTransform.ScaleY = 1.1;
            }

            scaleTransform.CenterX = canvas.Width / 2;
            scaleTransform.CenterY = canvas.Height / 2;

            canvas.RenderTransform = scaleTransform;
        }

        private void canvas_MouseLeave(object sender, MouseEventArgs e)
        {
            Canvas canvas = (Canvas)sender;
            ScaleTransform scaleTransform = new ScaleTransform();

            scaleTransform.ScaleX = 1;
            scaleTransform.ScaleY = 1;

            scaleTransform.CenterX = canvas.Width / 2;
            scaleTransform.CenterY = canvas.Height / 2;

            canvas.RenderTransform = scaleTransform;
        }




        #endregion otherMethods

        /************************************************************************************/
        /*****************************        DOK        ************************************/
        /************************************************************************************/

        #region DOK


        public void AddTermListToGraph(List<Term> termList)
        {
            AddTermListToGraph(termList, true);
        }

        public void AddTermListToGraph(List<Term> termList, bool createID)
        {
            foreach (Term term in termList)
            {
                if (createID)
                    term.TermID = terms.Count;
                AddTermToGraph(term);
            }
            //PaintTerm(termList[0]); //this
            //this    RepaintGraph();
        }


        public void AddTermToGraph(Term term)
        {
            bool exist = false;
            foreach (Term tt in terms)
                if (term.TermID == tt.TermID)
                    exist = true;
            if (!exist)
            {
                terms.Add(term);
                // PaintTerm(term);
                //this  RepaintGraph(); 
            }
        }


        public void RemoveTermFromGraph(Int32 TermID)
        {
            Collection<Term> termsPom = new Collection<Term>();
            foreach (Term tt in terms)

                if (TermID != tt.TermID)
                {
                    termsPom.Add(tt);
                }

            if (terms.Count != termsPom.Count)
            {
                terms = termsPom;
            //    RepaintGraph();
            }
        }

        public void RemoveTermsFromGraph()
        {
            terms.Clear();
            RepaintGraph();
        }


        public Int32 deepTerm(Int32 ID, Int32 num)
        {
            Int32 ret = num;
            foreach (Term tt in terms)
                if (tt.TermID == ID)
                {
                    if (tt.RootID != tt.TermID)
                    {
                        num++;
                        ret = deepTerm(tt.RootID, num);
                    }
                }
            return ret;
        }

        public Term getRootTerm()
        {
            foreach (Term tt in terms)
                if (tt.TermID == tt.RootID)
                    return tt;
            return new Term();
        }


        public Term getTerm(Int32 ID)
        {
            foreach (Term tt in terms)
                if (tt.TermID == ID)
                    return tt;
            return new Term();
        }


        // Vrací souřadnice bodů v kruhu okolo středu
        private LocationCollection GetPoints(int count, double centerX, double centerY, Int32 deep)
        {
            double width = 0.0004 + 0.0002 * (deep);
            LocationCollection points = new LocationCollection();

            for (int i = 0; i < count; i++)
            {
                double j = (double)i / (double)count;
                Point point = new Point(centerX + Math.Cos(j * 2 * Math.PI) * width,
                              centerY + Math.Sin(j * 2 * Math.PI) * width);
                points.Add(new Location(point.X, point.Y));
            }

            return points;
        }


        public void RepaintGraph()
        {
            mlTerm.Children.Clear();
            mlLine.Children.Clear();

            PaintTerm(getRootTerm());
            foreach (Term term in terms)
            {
                if (term.Bubble != null)
                {
                    if (term.Bubble.Size > 2)
                        term.Bubble.Size = term.Bubble.Size - 2;
                    if (term.Line.Size > 1)
                        term.Line.Size--;
                    PaintTermChild(term);
                }
            }
        }


        public void PaintTermChild(Term term)
        {
            Int32 deep = 0;
            if (term.TermID != getRootTerm().TermID)
                deep = deepTerm(term.RootID, 1);


            Int32 countChild = 0;
            foreach (Term rootTerm in terms)
                if ((rootTerm.RootID == term.TermID) && (rootTerm.TermID != getRootTerm().TermID))
                    countChild++;

            LocationCollection loc = GetPoints(countChild, term.Bubble.Location.Latitude, term.Bubble.Location.Longitude, deep);
            Int32 i = 0;

            foreach (Term childTerm in terms)
            {
                if ((childTerm.RootID == term.TermID) && (childTerm.TermID != getRootTerm().TermID))
                {
                    childTerm.Bubble.Location = loc[i];
                    mlLine.AddChild(AddLineToLayer(term.Bubble.Location, childTerm.Bubble.Location, childTerm.Line.Color, childTerm.Line.Size));
                    mlTerm.AddChild(AddEllipseToLayer(childTerm.Bubble.Location, childTerm.Bubble.Color, childTerm.Name, Convert.ToInt32(childTerm.Bubble.Size), childTerm.TermID)); //this

                    i++;
                }
            }
        }


        public void PaintTerm(Term term)
        {
            if (term.Bubble != null)
                mlTerm.AddChild(AddEllipseToLayer(term.Bubble.Location, term.Bubble.Color, term.Name, Convert.ToInt32(term.Bubble.Size), term.TermID));
        }


        public void SetBackground()
        {
            bback.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
            bback.VerticalAlignment = VerticalAlignment.Center;
            bback.HorizontalAlignment = HorizontalAlignment.Center;
            bback.BorderThickness = new Thickness(2);
            bback.CornerRadius = new CornerRadius(5);
            bback.Opacity = 1;
            bback.Padding = new Thickness(5);
            bback.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
            bback.Width = myMap.ActualWidth;
            bback.Height = myMap.ActualHeight;
        }


        #endregion DOK

        /************************************************************************************/
        /*****************************        GAL        ************************************/
        /************************************************************************************/

        //ciselnik barev
        Color[] lovColors = {Color.FromArgb(255,176,23,31),
                                Color.FromArgb(255,238,106,167),
                                Color.FromArgb(255,191,62,255),	
                                Color.FromArgb(255,67,110,238),
                                Color.FromArgb(255,79,148,205),
                                Color.FromArgb(255,50,205,50),
                                Color.FromArgb(255,154,205,50),  	
                                Color.FromArgb(255,238,238,0),
                                Color.FromArgb(255,238,0,0),
                                Color.FromArgb(255,238,180,34),
                                Color.FromArgb(255,255,140,0),	
                                Color.FromArgb(255,238,44,44),
                                Color.FromArgb(255,176,176,176)};

        //index posledni pouzite barvy
        Int32 lastColorIndex = 0;

        #region GAL

        //Vykreslí graf všech termů a hran
        public void GAL_PaintGraph()
        {
            mlTerm.Children.Clear();
            mlLine.Children.Clear();
            Int32 x = 0;

            Random rand = new Random();
            foreach (Term term in terms)
            {
                term.Visible = false;
                term.Bubble.Location = new Location(rand.Next(-200, 200) / 100000.0, rand.Next(-200, 200) / 100000.0);
            }

            foreach (Term term in terms)
            {
                GAL_CountTermChildLocation(term);
            }

            foreach (Term term in terms)
            {
                GAL_PaintTermChildLine(term);
                PaintTerm(term);
                x++;
            }

            MessageNew("Celkem Termů: " + x.ToString());
        }

        //Spočítá souřadnice nevykreslených potomků vstupního termu
        private void GAL_CountTermChildLocation(Term term)
        {
            Int32 countChild = term.Child.Count;
            if (countChild != 0)
            {
                Int32 countChildInVisible = GAL_CountInvisibleChild(term.Child);
                LocationCollection loc = GetPoints(countChildInVisible, term.Bubble.Location.Latitude, term.Bubble.Location.Longitude, 1);
                int j = 0;
                for (int i = 0; i < countChild; i++)
                    foreach (Term childTerm in terms)
                        if (childTerm.TermID == term.Child[i].ID)
                            if (!childTerm.Visible)
                            {
                                childTerm.Bubble.Location = loc[j];
                                childTerm.Visible = true;
                                j++;
                            }
            }
        }

        //Vykreslí hrany k potomkům vstupního termu
        private void GAL_PaintTermChildLine(Term term)
        {
            Random random = new Random();
            Int32 colorIndex = random.Next(lovColors.Length);

            while (colorIndex == lastColorIndex)
            {
                colorIndex = random.Next(lovColors.Length);
            }

            lastColorIndex = colorIndex;

            Int32 countChild = term.Child.Count;
            if (countChild != 0)
            {
                for (int i = 0; i < countChild; i++)
                    foreach (Term childTerm in terms)
                        if ((childTerm.TermID == term.Child[i].ID) && (childTerm.Bubble != null))
                            mlLine.AddChild(AddLineToLayer(term.Bubble.Location, childTerm.Bubble.Location, lovColors[lastColorIndex], term.Child[i].SizeLine * 2)); //childTerm.Line.Color childTerm.Line.Size
            }
        }

        //vrací počet nezobrazených potomků
        private Int32 GAL_CountInvisibleChild(List<TermChild> childTerms)
        {
            int countVisible = 0;
            foreach (TermChild term in childTerms)
                if (getTerm(term.ID).Visible == false) countVisible++;

            return countVisible;
        }

        //Vykreslí hranu od termu k potomkovi, který leží na této cestě
        private void GAL_PaintLinePath(Term term, Int32[] pathIDs)
        {
            Int32 countChild = term.Child.Count;
            if (countChild != 0)
            {
                for (int i = 0; i < countChild; i++)
                    foreach (Term childTerm in terms)
                        if (childTerm.TermID == term.Child[i].ID)
                            foreach (Int32 pathID in pathIDs)
                                if (term.Child[i].ID == pathID)
                                    mlLine.AddChild(AddLineToLayer(term.Bubble.Location, childTerm.Bubble.Location, Color.FromArgb(200, 238, 0, 0), 10));
            }
        }





        //Překreslí graf - tak, aby všechny Termy měly stejnou barvu a velikost
        public void GAL_RepaintGraph()
        {
            mlTerm.Children.Clear();
            mlLine.Children.Clear();

            foreach (Term term in terms)
            {
                term.Bubble.Color = Color.FromArgb(255, 238, 180, 34);
                term.Bubble.Size = 6;
                GAL_PaintTermChildLine(term);
                PaintTerm(term);
            }
            MessageNew("Celkem Termů: " + terms.Count.ToString());
        }

        //Překreslí graf - tak, aby všechny Termy měly stejnou barvu a velikost
        public void GAL_RepaintGraph2()
        {
            mlTerm.Children.Clear();
            mlLine.Children.Clear();

            foreach (Term term in terms)
            {
                //term.Bubble.Size = 6;
                GAL_PaintTermChildLine(term);
                PaintTerm(term);
            }
            MessageNew("Celkem Termů: " + terms.Count.ToString());
        }

        //Vylreslí cestu dle pole ID
        public void GAL_PaintPath(Int32[] pathIDs)
        {
            mlTerm.Children.Clear();
            mlLine.Children.Clear();

            foreach (Term term in terms)
            {
                bool isInPath = false;
                foreach (Int32 pathID in pathIDs)
                    if (term.TermID == pathID)
                        isInPath = true;
                if (!isInPath)
                {
                    term.Bubble.Color = Color.FromArgb(255, 238, 180, 34);
                    term.Bubble.Size = 6;
                    PaintTerm(term);
                }
                GAL_PaintTermChildLine(term);
            }

            foreach (Term term in terms)
            {
                bool isInPath = false;
                foreach (Int32 pathID in pathIDs)
                    if (term.TermID == pathID)
                        isInPath = true;

                if (isInPath)
                {
                    term.Bubble.Color = Color.FromArgb(200, 238, 0, 0);
                    term.Bubble.Size = 10;
                    PaintTerm(term);
                    GAL_PaintLinePath(term, pathIDs);
                }
            }
        }

        #endregion GAL

    }
}
